use crate::{data::ResponseObject, invoker::TryIntoResponseObject};

use common_base::{
    prelude::*,
    sqlx::{Connection, MySqlConnection},
};

use super::db_type::DbType;

#[derive(Debug)]
pub struct DbConnection {
    pub(crate) db_type: DbType,
    pub(crate) conn: Option<MySqlConnection>,
    pub(crate) threshold: i32,
}

const THRESHOLD_DEFAULT: i32 = 2000;

impl DbConnection {
    pub fn new(db_type: DbType) -> Self {
        Self {
            db_type,
            conn: None,
            threshold: THRESHOLD_DEFAULT,
        }
    }

    pub async fn close(&mut self) {
        let conn = std::mem::take(&mut self.conn);
        if let Some(conn) = conn {
            if let Err(e) = conn.close().await {
                warn!("close database connection failed, cause: {}", e);
            }
        }
    }
}

impl DbConnection {
    pub fn get_conn_mut(&mut self) -> Option<&mut MySqlConnection> {
        self.conn.as_mut()
    }

    pub fn take_connection(&mut self) -> MySqlConnection {
        self.conn.take().unwrap()
    }

    pub fn restore_connection(&mut self, conn: Option<MySqlConnection>) {
        self.conn = conn
    }
}

impl TryIntoResponseObject for DbConnection {
    fn try_into_ro(&self) -> Result<ResponseObject> {
        Err(ErrorCode::InvokerNotFound(
            "DbConnection can not transmute into ResponseObject",
        ))
    }
}
